#pragma once

#include <string>
#include <functional>
#include <unordered_map>
#include <cppwinks/network/http/Http.h>

class HttpUriRegistrar
{
public:
    using HttpHandler = std::function<network::HttpReply(const network::HttpRequest &)>;
    void registerGetHandler(const std::string &uri, HttpHandler cb);
    void registerPostHandler(const std::string &uri, HttpHandler cb);
    HttpHandler getHandler(const std::string &uri);
    HttpHandler PostHandler(const std::string &uri);

private:
    std::unordered_map<std::string, HttpHandler> get_mapping, post_mapping;
};

#define GetMapping(uri, class_name, method)                                                                                                                        \
    namespace HttpUriMappingGeneration                                                                                                                             \
    {                                                                                                                                                              \
        struct Generation##class_name##method                                                                                                                      \
        {                                                                                                                                                          \
            Generation##class_name##method()                                                                                                                       \
            {                                                                                                                                                      \
                MSingletonFactory *factory = MSingletonFactory::getMFactory();                                                                                     \
                class_name *data = factory->getSingleton<class_name>(#class_name);                                                                                 \
                factory->getSingleton<HttpUriRegistrar>("HttpUriRegistrar")->registerGetHandler(uri, std::bind(&class_name::method, data, std::placeholders::_1)); \
            }                                                                                                                                                      \
        };                                                                                                                                                         \
        Generation##class_name##method generation##class_name##method;                                                                                             \
    }

#define PostMapping(uri, class_name, method)                                                                                                                        \
    namespace HttpUriMappingGeneration                                                                                                                              \
    {                                                                                                                                                               \
        struct Generation##class_name##method                                                                                                                       \
        {                                                                                                                                                           \
            Generation##class_name##method()                                                                                                                        \
            {                                                                                                                                                       \
                MSingletonFactory *factory = MSingletonFactory::getMFactory();                                                                                      \
                class_name *data = factory->getSingleton<class_name>(#class_name);                                                                                  \
                factory->getSingleton<HttpUriRegistrar>("HttpUriRegistrar")->registerPostHandler(uri, std::bind(&class_name::method, data, std::placeholders::_1)); \
            }                                                                                                                                                       \
        };                                                                                                                                                          \
        Generation##class_name##method generation##class_name##method;                                                                                              \
    }
